package com.yungam.imcs.controller.equip_stable.anslysis;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yungam.common.bean.equip.EquipStableScore;
import com.yungam.common.bean.equip.Equipment;
import com.yungam.common.response.RetDTO;
import com.yungam.common.service.EquipStableScoreService;
import com.yungam.common.service.EquipmentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Api(tags = "设备稳定性分析页面接口")
@RestController
@RequestMapping("/equipStableAnalysis")
public class EquipStableAnalysisController {

    /**
     * 设备稳定性统计的设备
     */
    private final static Integer[] EQU_IDS = {90020, 90021, 90050, 90070, 90071, 90090, 90091};

    @Resource
    private EquipStableScoreService equipStableScoreService;
    @Resource
    private EquipmentService equipmentService;

    /**
     * 只需要求月和年的平均得分
     */
    @ApiOperation("设备稳定性统计-周|月|年平均得分")
    @GetMapping("/stableScores")
    public RetDTO<?> getStableScores() {
        ZoneId zid = ZoneId.systemDefault();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd"),
                df2 = DateTimeFormatter.ofPattern("MM-dd"),
                df3 = DateTimeFormatter.ofPattern("yyyy-MM");
        LocalDateTime now = LocalDateTime.now();
        // 获取7个设备对应的名称
        Map<Integer, String> equipInfos = Maps.newHashMap();
        List<Equipment> equipList = equipmentService.list(new QueryWrapper<Equipment>()
                .in("equ_id", EQU_IDS)
                .select(Equipment.class, col -> !col.getProperty().equals("equImg")));
        for (Equipment equip : equipList) equipInfos.put(equip.getEquId(), equip.getEquName());

        // 获取过去一个月的所有数据
        LocalDateTime lastWeek = now.minusDays(29);
        String start = lastWeek.format(df), end = now.format(df);
        start += " 00:00:00"; end += " 23:59:59";
        List<EquipStableScore> dataList = equipStableScoreService.list(new QueryWrapper<EquipStableScore>()
                .between("create_time", start, end));
        // 按照`日期-设备ID`的格式存入Map
        Map<String, List<EquipStableScore>> map = Maps.newHashMap();
        for (EquipStableScore es : dataList) {
            String dateStr = LocalDateTime.ofInstant(
                    es.getCreateTime().toInstant(), zid).format(df2);
            String key = dateStr + "-" + es.getEquId();
            List<EquipStableScore> od = map.getOrDefault(key, Lists.newArrayList());
            od.add(es);
            map.put(key, od);
        }
        // 计算每天每个设备的平均得分
        Map<Integer, List<Integer>> scoreOfEquip = Maps.newHashMap();
        for (Integer equId : EQU_IDS) {
            for (int i = 29; i >= 0; i--) {
                String dateStr = now.minusDays(i).format(df2);
                String key = dateStr + "-" + equId;
                List<EquipStableScore> equList = map.getOrDefault(key, Lists.newArrayList());
                int avgScore = 0;
                if (equList.size() > 0) {
                    int sum = equList.stream().map(EquipStableScore::getScore).reduce((x, y) -> x + y).orElse(0);
                    avgScore = sum / equList.size();
                    if (avgScore > 100) avgScore = 99;
                }
                List<Integer> scoreList = scoreOfEquip.getOrDefault(equId, Lists.newArrayList());
                scoreList.add(avgScore);
                scoreOfEquip.put(equId, scoreList);
            }
        }
        // 整合数据
        List<Map<String, Object>> stableData = Lists.newArrayList();
        for (Integer equId : EQU_IDS) {
            Map<String, Object> item = Maps.newHashMap();
            List<Integer> scores = scoreOfEquip.getOrDefault(equId, Lists.newArrayList());
            if (scores.size() == 0) {
                for (int i = 0; i < 30; i++) scores.add(0);
            }
            item.put("equId", equId);
            item.put("data", scores);
            item.put("name", equipInfos.getOrDefault(equId, ""));
            stableData.add(item);
        }
        List<String> xData = Lists.newArrayList();
        for (int i = 29; i >= 0; i--) {
            String dateStr = now.minusDays(i).format(df2);
            xData.add(dateStr);
        }

        // 获取过去一年的所有数据
        LocalDateTime yearStart = now.minusMonths(11);
        start = df.format(yearStart) + " 00:00:00";
        end = df.format(now) + " 23:59:59";
        List<EquipStableScore> yearDataList = equipStableScoreService.list(new QueryWrapper<EquipStableScore>()
                .between("create_time", start, end));

        // 按照`年月-设备ID`的格式存入Map
        Map<String, List<EquipStableScore>> mapOfYear = Maps.newHashMap();
        for (EquipStableScore es : yearDataList) {
            String dateStr = LocalDateTime.ofInstant(
                    es.getCreateTime().toInstant(), zid).format(df3);
            String key = dateStr + "-" + es.getEquId();
            List<EquipStableScore> od = mapOfYear.getOrDefault(key, Lists.newArrayList());
            od.add(es);
            mapOfYear.put(key, od);
        }
        // 计算每月每个设备的平均得分
        Map<Integer, List<Integer>> yearScoreOfEquip = Maps.newHashMap();
        for (Integer equId : EQU_IDS) {
            for (int i = 0; i < 12; i++) {
                String dateStr = yearStart.plusMonths(i).format(df3);
                String key = dateStr + "-" + equId;
                List<EquipStableScore> equList = mapOfYear.getOrDefault(key, Lists.newArrayList());
                int avgScore = 0;
                if (equList.size() > 0) {
                    int sum = equList.stream().map(EquipStableScore::getScore).reduce((x, y) -> x + y).orElse(0);
                    avgScore = sum / equList.size();
                    if (avgScore > 100) avgScore = 99;
                }
                List<Integer> scoreList = yearScoreOfEquip.getOrDefault(equId, Lists.newArrayList());
                scoreList.add(avgScore);
                yearScoreOfEquip.put(equId, scoreList);
            }
        }

        List<Map<String, Object>> yearStableData = Lists.newArrayList();
        for (Integer equId : EQU_IDS) {
            Map<String, Object> item = Maps.newHashMap();
            List<Integer> scores = yearScoreOfEquip.getOrDefault(equId, Lists.newArrayList());
            if (scores.size() == 0) {
                for (int i = 0; i < 30; i++) scores.add(0);
            }
            item.put("equId", equId);
            item.put("data", scores);
            item.put("name", equipInfos.getOrDefault(equId, ""));
            yearStableData.add(item);
        }

        List<String> yearXData = Lists.newArrayList();
        for (int i = 0; i < 12; i++) {
            String dateStr = yearStart.plusMonths(i).format(df3);
            dateStr = dateStr.substring(dateStr.indexOf('-') + 1) + '月';
            yearXData.add(dateStr);
        }
        // 整理最终数据
        // 月
        Map<String, Object> month = Maps.newHashMap();
        month.put("xData", xData);
        month.put("yData", stableData);
        // 年
        Map<String, Object> year = Maps.newHashMap();
        year.put("xData", yearXData);
        year.put("yData", yearStableData);
        List<Map<String, Object>> ans = Lists.newArrayList(month, year);
        return RetDTO.data(ans);
    }

    /**
     * 设备得分统计(昨日 | 周 | 历史)
     */
    @ApiOperation("设备得分统计(昨日 | 周 | 历史)")
    @GetMapping("/scoreSummary")
    public RetDTO<?> scoreSummary() {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        // 获取所有的历史数据
        List<EquipStableScore> historyList = equipStableScoreService.list();
        if (historyList.size() == 0) return RetDTO.data(null);

        Map<Integer, List<EquipStableScore>> mapByEquId = Maps.newHashMap();
        for (EquipStableScore es : historyList) {
            List<EquipStableScore> od = mapByEquId.getOrDefault(es.getEquId(), Lists.newArrayList());
            od.add(es);
            mapByEquId.put(es.getEquId(), od);
        }

        // 求历史平均分
        Map<Integer, Integer> historyScoreMap = Maps.newHashMap();
        for (Integer equId : mapByEquId.keySet()) {
            List<EquipStableScore> list = mapByEquId.getOrDefault(equId, Lists.newArrayList());
            Integer reduce = list.stream().map(EquipStableScore::getScore)
                    .reduce(Integer::sum).orElse(0);
            Integer avgScore = list.size() > 0 ? reduce / list.size() : 0;
            historyScoreMap.put(equId, avgScore);
        }

        // 昨日数据
        LocalDateTime lastDay = now.minusDays(1);
        String dateStr = lastDay.format(df);
        String start = dateStr + " 00:00:00", end = dateStr + " 23:59:59";
        List<EquipStableScore> lastDayList = equipStableScoreService.list(new QueryWrapper<EquipStableScore>()
                .between("create_time", start, end));

        Map<Integer, List<EquipStableScore>> mapByEquIdoOfLastDay = Maps.newHashMap();
        for (EquipStableScore es : lastDayList) {
            List<EquipStableScore> od = mapByEquIdoOfLastDay.getOrDefault(es.getEquId(), Lists.newArrayList());
            od.add(es);
            mapByEquIdoOfLastDay.put(es.getEquId(), od);
        }

        // 求昨日平均分
        Map<Integer, Integer> lastDayScoreMap = Maps.newHashMap();
        for (Integer equId : mapByEquIdoOfLastDay.keySet()) {
            List<EquipStableScore> list = mapByEquIdoOfLastDay.getOrDefault(equId, Lists.newArrayList());
            Integer reduce = list.stream().map(EquipStableScore::getScore)
                    .reduce(Integer::sum).orElse(0);
            Integer avgScore = list.size() > 0 ? reduce / list.size() : 0;
            lastDayScoreMap.put(equId, avgScore);
        }

        // 过去一周数据
        LocalDateTime lastWeek = now.minusDays(6);
        start = lastWeek.format(df) + " 00:00:00"; end = now.format(df) + " 23:59:59";
        List<EquipStableScore> lastWeekList = equipStableScoreService.list(new QueryWrapper<EquipStableScore>()
                .between("create_time", start, end));

        Map<Integer, List<EquipStableScore>> mapByEquIdoOfLastWeek = Maps.newHashMap();
        for (EquipStableScore es : lastWeekList) {
            List<EquipStableScore> od = mapByEquIdoOfLastWeek.getOrDefault(es.getEquId(), Lists.newArrayList());
            od.add(es);
            mapByEquIdoOfLastWeek.put(es.getEquId(), od);
        }

        // 求上周平均分
        Map<Integer, Integer> lastWeekScoreMap = Maps.newHashMap();
        for (Integer equId : mapByEquIdoOfLastWeek.keySet()) {
            List<EquipStableScore> list = mapByEquIdoOfLastWeek.getOrDefault(equId, Lists.newArrayList());
            Integer reduce = list.stream().map(EquipStableScore::getScore)
                    .reduce(Integer::sum).orElse(0);
            Integer avgScore = list.size() > 0 ? reduce / list.size() : 0;
            lastWeekScoreMap.put(equId, avgScore);
        }

        // 获取7个设备的信息
        List<Equipment> equipList = equipmentService.list(new QueryWrapper<Equipment>()
                .in("equ_id", EQU_IDS)
                .select(Equipment.class, col -> !col.getProperty().equals("equImg")));
        Map<Integer, Equipment> equipMap = Maps.newHashMap();
        for (Equipment equip : equipList) equipMap.put(equip.getEquId(), equip);

        // 整合数据
        Map<String, Object> ans = Maps.newHashMap();
        ans.put("lastDay", lastDayScoreMap);
        ans.put("lastWeek", lastWeekScoreMap);
        ans.put("history", historyScoreMap);
        ans.put("equips", equipMap);
        return RetDTO.data(ans);
    }

    /**
     * 计算得分趋势和总体平均分
     */
    @ApiOperation("计算得分趋势和总体平均分")
    @GetMapping("trendAndTotalAvg")
    public RetDTO<?> trendAndTotalAvg() {
        ZoneId zid = ZoneId.systemDefault();
        // 得分趋势只需要计算月和年, 周从月的数据中截取后7天即可
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd"), df2 = DateTimeFormatter.ofPattern("yyyy-MM");

        // 计算月
        LocalDateTime monthStart = now.minusDays(29);
        String start = df.format(monthStart) + " 00:00:00",
        end = df.format(now) + " 23:59:59";
        List<EquipStableScore> monthList = equipStableScoreService.list(new QueryWrapper<EquipStableScore>()
                .between("create_time", start, end));
        // 按照天分类
        List<Integer> monthScoreList = Lists.newArrayList(); // 月每天的平均分集合
        Map<String, List<Integer>> mapByDateOfMonth = Maps.newHashMap();
        for (EquipStableScore es : monthList) {
            String key = LocalDateTime.ofInstant(es.getCreateTime().toInstant(), zid).format(df);
            List<Integer> od = mapByDateOfMonth.getOrDefault(key, Lists.newArrayList());
            od.add(es.getScore());
            mapByDateOfMonth.put(key, od);
        }
        for (int i = 0; i < 30; i++) {
            String key = monthStart.plusDays(i).format(df);
            List<Integer> od = mapByDateOfMonth.getOrDefault(key, Lists.newArrayList());
            int avgScore = 0;
            if (od.size() > 0) {
                avgScore = od.stream().reduce(Integer::sum).orElse(0) / od.size();
            }
            monthScoreList.add(avgScore);
        }

        // 计算年
        LocalDateTime yearStart = now.minusMonths(11);
        start = df.format(yearStart) + " 00:00:00";
        end = df.format(now) + " 23:59:59";
        List<EquipStableScore> yearList = equipStableScoreService.list(new QueryWrapper<EquipStableScore>()
                .between("create_time", start, end));
        // 按照月分类
        List<Integer> yearScoreList = Lists.newArrayList();
        Map<String, List<Integer>> mapByDateOfYear = Maps.newHashMap();
        for (EquipStableScore es : yearList) {
            String key = LocalDateTime.ofInstant(es.getCreateTime().toInstant(), zid).format(df2);
            List<Integer> od = mapByDateOfMonth.getOrDefault(key, Lists.newArrayList());
            od.add(es.getScore());
            mapByDateOfYear.put(key, od);
        }
        for (int i = 0; i < 12; i++) {
            String key = yearStart.plusMonths(i).format(df2);
            List<Integer> od = mapByDateOfYear.getOrDefault(key, Lists.newArrayList());
            int avgScore = 0;
            if (od.size() > 0) {
                avgScore = od.stream().reduce(Integer::sum).orElse(0) / od.size();
            }
            yearScoreList.add(avgScore);
        }

        // 计算昨日总平均分和历史总平均分
        int historyScoreAvg = 0, lastDayScoreAvg = 0;
        List<Integer> allScores = equipStableScoreService.list().stream().map(EquipStableScore::getScore).collect(Collectors.toList());
        if (allScores.size() > 0) {
            historyScoreAvg = allScores.stream().reduce(Integer::sum).orElse(0) / allScores.size();
        }
        LocalDateTime lastDay = now.minusDays(1);
        start = lastDay.format(df) + " 00:00:00"; end = now.format(df) + " 23:59:59";
        List<Integer> lastDayScores = equipStableScoreService.list(new QueryWrapper<EquipStableScore>()
                        .between("create_time", start, end))
                        .stream().map(EquipStableScore::getScore).collect(Collectors.toList());
        if (lastDayScores.size() > 0) {
            lastDayScoreAvg = allScores.stream().reduce(Integer::sum).orElse(0) / allScores.size();
        }

        // 整理数据
        Map<String, Object> ans = Maps.newHashMap();
        ans.put("month", monthScoreList);
        ans.put("year", yearScoreList);
        ans.put("historyScoreAvg", historyScoreAvg);
        ans.put("lastDayScoreAvg", lastDayScoreAvg);
        return RetDTO.data(ans);
    }

}
